package com.revzone.demo001.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.revzone.demo001.entity.Qrcode;
import com.revzone.demo001.service.QrcodeService;
import com.revzone.demo001.mapper.QrcodeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* @author Admin
* @description 针对表【qrcode】的数据库操作Service实现
* @createDate 2025-07-01 14:14:57
*/
@Service
public class QrcodeServiceImpl extends ServiceImpl<QrcodeMapper, Qrcode>
    implements QrcodeService{

    @Autowired
    private StringRedisTemplate redisTemplate; // 用于操作Redis的模板

    // 日期格式化器，格式为YYMMDD
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");
    // 流水号最大值
    private static final long MAX_SEQUENCE = 9999L;
    // 流水号格式化，左侧补零到4位
    private static final String SEQUENCE_FORMAT = "%04d";

    /**
     * 批量生成唯一码，并插入数据库，填充 creat_time、update_time、remarks、url、type 字段
     *
     * @param productType 产品类型标识 (C 或 T) int类型0是T,1是C
     * @param count       要生成的码数量
     * @param urlPrefix   url 域名头（如 http://cx.panpass.com/?fw=）
     * @param remarks     备注
     * @return 唯一码列表
     * @throws RuntimeException 如果流水号超出当日上限
     */
    public List<String> generateUniqueCodes(Integer productType, Integer count, String urlPrefix, String remarks) {
        if (count <= 0) {
            return new ArrayList<>();
        }
        if (productType != 0 && productType != 1) {
            throw new IllegalArgumentException("产品类型标识必须是 'C' 或 'T'");
        }
        char Type;
        if(productType == 0){
            Type = 'T';
        }
        else{
            Type = 'C';
        }

        LocalDate today = LocalDate.now();
        String dateStr = today.format(DATE_FORMATTER); // 获取YYMMDD格式的日期字符串

        // 构建 Redis key
        String redisKey = String.format("%s:%c:counter", dateStr, Type);

        // 获取第二天零点的时间戳，用于设置过期时间
        LocalDateTime nextDayMidnight = today.plusDays(1).atStartOfDay();
        long expireTimeSeconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), nextDayMidnight);

        List<String> codes = new ArrayList<>(count);

        // 使用 Redis 的 Pipeline 或 Lua 脚本进行批量递增以提高效率（此处简化为循环递增）
        // 对于小批量，循环递增也可以接受。对于大批量，建议使用 pipeline。
        // 或者直接使用 incrby 来批量增加一个批次的数量
        Long startSequence = redisTemplate.opsForValue().increment(redisKey, 1); // 第一次递增获取起始值

        // 如果是当天第一次操作，需要设置过期时间
        if (startSequence == 1) {
            redisTemplate.expire(redisKey, expireTimeSeconds, TimeUnit.SECONDS);
        }

        // 再次检查并设置过期时间，以防万一（例如，在设置expire前服务重启）
        // 确保每次操作都尝试设置过期时间，Redis会在key存在时更新过期时间，不存在时设置
        redisTemplate.expire(redisKey, expireTimeSeconds, TimeUnit.SECONDS);


        // 批量递增计数器
        Long finalSequence = redisTemplate.opsForValue().increment(redisKey, count -1); // 累加剩余数量

        // 检查是否超出当日上限
        if (finalSequence > MAX_SEQUENCE) {
            // 如果超出了，需要回滚 Redis 计数器（非常重要！）
            redisTemplate.opsForValue().increment(redisKey, -(count)); // 回滚本次递增的数量
            throw new RuntimeException("今日 " + Type + " 类型码的生成数量已达上限: " + MAX_SEQUENCE);
        }

        LocalDateTime now = LocalDateTime.now();
        for (long i = startSequence; i <= finalSequence; i++) {
            String sequenceStr = String.format(SEQUENCE_FORMAT, i);
            String code = dateStr + Type + sequenceStr;
            codes.add(code);
            // 插入数据库
            Qrcode qrcode = new Qrcode();
            qrcode.setName(code);
            qrcode.setCreat_time(now);
            qrcode.setUpdate_time(now);
            qrcode.setRemarks(remarks);
            qrcode.setType(productType);
            if (urlPrefix != null && !urlPrefix.isEmpty()) {
                qrcode.setUrl(urlPrefix + code);
            } else {
                qrcode.setUrl(code);
            }
            this.save(qrcode);
        }
        return codes;
    }
    //003件到008
    public String ExportQrcode(String startcount, String endcount, String exportDir) {
        if (startcount == null || endcount == null) {
            return "参数错误";
        }
        // 构造查询条件，name区间查询
        QueryWrapper<Qrcode> wrapper = new QueryWrapper<>();
        wrapper.ge("name", startcount).le("name", endcount).orderByAsc("name");
        List<Qrcode> qrcodes = this.list(wrapper);

        // 收集url
        List<String> urls = new ArrayList<>();
        for (Qrcode qrcode : qrcodes) {
            if (qrcode.getUrl() != null) {
                urls.add(qrcode.getUrl());
            }
        }

        // 写入txt
        exportDir = (exportDir != null) ? exportDir : "D:/revzone/Otoc/Export/";//如果是null使用默认值
        File dir = new File(exportDir);
        if (!dir.exists()) dir.mkdirs();
        String fileName = "qrcode_export_" + startcount.substring(startcount.length() - 4) + "_" + endcount.substring(endcount.length() - 4) + ".txt";
        File txtFile = new File(dir, fileName);
        try (java.io.BufferedWriter writer = new java.io.BufferedWriter(new java.io.FileWriter(txtFile))) {
            for (String url : urls) {
                writer.write(url);
                writer.newLine();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "导出失败：" + e.getMessage();
        }
        return "导出成功，文件路径：" + txtFile.getAbsolutePath();
    }
}




